﻿import QtQuick 2.4
import QtQuick 2.13
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.13


// 导入自定义包
import com.mycompany.customType 1.0

SearchForm{
    /*
    // 设备列表数据模型
    ListModel {
        id: bluetoothDeviceModel

        ListElement {
            deviceName: "HC-05"
            deviceAddr: "20:00:15:25::65:87"
            sectionInfo: "HC-05<br/><font size=\"7\" color=\"gray\">20:00:15:25::65:87</font>"
            serviceName: "Serial Port Profile"
            socketProtocol: 2
            serviceClassUuid: "{00001101-0000-1000-8000-00805f9b34fb}"
        }
        ListElement {
            deviceName: "HC-05"
            deviceAddr: "20:00:15:25::65:87"
            sectionInfo: "HC-05<br/><font size=\"7\" color=\"gray\">20:00:15:25::65:87</font>"
            addr: "20:00:15:25::65:871"
            serviceName: ""
            socketProtocol: 1
            serviceClassUuid: "{00000000-0000-1000-8000-00805fjksdf4}"
        }
        ListElement {
            deviceName: "HC-05"
            deviceAddr: "20:00:15:25::65:87"
            sectionInfo: "HC-05<br/><font size=\"7\" color=\"gray\">20:00:15:25::65:87</font>"
            addr: "20:00:15:25::65:871"
            serviceName: ""
            socketProtocol: 1
            serviceClassUuid: "{00000000-1223-1000-8000-00805fjksdf4}"
        }
    }
    */

    Component.onCompleted: {
    }

    // 写Descriptor Dialog
    Dialog {
        id: dialogSetDescriptor
        visible: false
        anchors.centerIn: parent
        focus: true
        modal: true
        title: qsTr("设置Descriptor")
        standardButtons: Dialog.NoButton
        property string descriptorName: ""
        property string descriptorUuid: ""
        property string characteristicUuid: ""
        property string serviceUuid: ""
        property string orgVal: ""
        function setDescriptorValue(descriptorName, descriptorUuid
                                    , characteristicUuid
                                    , serviceUuid
                                    , val)
        {
            this.descriptorName = descriptorName;
            this.descriptorUuid = descriptorUuid;
            this.characteristicUuid = characteristicUuid;
            this.serviceUuid = serviceUuid;

            dlgDescriptorValue.text = val;
        }
        footer: ToolBar {
            position: ToolBar.Footer
            background: Rectangle{
                anchors.fill: parent
                color: "white"
                border.color: "black"
                border.width: 1
                Rectangle{// 边框,绘制被遮盖的dlg边框
                    color: parent.color
                    border.width: 0
                    anchors.fill: parent
                    anchors.topMargin: 0
                    anchors.rightMargin: 1
                    anchors.bottomMargin: 1
                    anchors.leftMargin: 1
                }
            }
            Row {
                anchors.fill: parent
                layoutDirection: Qt.RightToLeft
                spacing: 1
                padding: 1  // 避免遮盖边框

                Button {
                    text: qsTr("取消")
                    onClicked: {
                        dialogSetDescriptor.reject();
                    }
                }
                Button {
                    text: qsTr("设置")
                    onClicked: {
                        dialogSetDescriptor.accept();
                    }
                }
            }
        }
        onAccepted: {
            if(dlgDescriptorValue.text.length > 0)
            {
                var charsetType = BluetoothCtrlSingleton.EnumCharset_GBK;
                switch(dlgDescriptorCharset.currentText)
                {
                case qsTr("HEX"):
                    charsetType = BluetoothCtrlSingleton.EnumCharset_HEX;
                    break;
                case qsTr("GBK"):
                    charsetType = BluetoothCtrlSingleton.EnumCharset_GBK;
                    break;
                case qsTr("UTF8"):
                    charsetType = BluetoothCtrlSingleton.EnumCharset_UTF8;
                    break;
                case qsTr("UNICODE"):
                    charsetType = BluetoothCtrlSingleton.EnumCharset_UNICODE;
                    break;
                }
                BluetoothCtrlSingleton.writeLowEnergyDescriptor(descriptorName, descriptorUuid
                                                                , characteristicUuid
                                                                , serviceUuid
                                                                , dlgDescriptorValue.text
                                                                , charsetType
                                                                );
            }
        }
        contentItem: Item {
            Column {
                spacing: 3
                ComboBox {
                    id: dlgDescriptorCharset
                    width: 70
                    height: 25
                    currentIndex: 1
                    model: ListModel {
                        //id: model
                        ListElement {
                            text: qsTr("HEX")
                        }
                        ListElement {
                            text: qsTr("GBK")
                        }
                        ListElement {
                            text: qsTr("UTF8")
                        }
                        ListElement {
                            text: qsTr("UNICODE")
                        }
                    }
                    delegate: ItemDelegate {
                        width: dlgDescriptorCharset.width
                        height: dlgDescriptorCharset.height
                        contentItem: Text {
                            text: modelData
                            opacity: enabled ? 1.0 : 0.3
                            color: "#21be2b"
                            font: dlgDescriptorCharset.font
                            //elide: Text.ElideRight
                            verticalAlignment: Text.AlignVCenter
                            horizontalAlignment: Text.AlignHCenter
                        }
                        highlighted: dlgDescriptorCharset.highlightedIndex === index
                    }
                    contentItem: Text {
                        text: dlgDescriptorCharset.displayText
                        font: dlgDescriptorCharset.font
                        opacity: enabled ? 1.0 : 0.3
                        color: dlgDescriptorCharset.pressed ? "#17a81a" : "#21be2b"
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                        //elide: Text.ElideRight
                    }
                    background: Rectangle {
                        opacity: enabled ? 1.0 : 0.3
                        border.color: dlgDescriptorCharset.pressed ? "#17a81a" : "#21be2b"
                        border.width: dlgDescriptorCharset.visualFocus ? 2 : 1
                        radius: 2
                    }
                    indicator: Item {
                        // 取消显示indicator
                        width: 0
                        height: 0
                    }
                }
                TextField {
                    id: dlgDescriptorValue
                    focus: true
                    readOnly: false
                }
            }
        }
    }
    // 设备列表delegate-------------------------------------------------------
    Component {
        id: delegateDeviceList
        //
        Item {
            id: delegateDeviceItem
            property int rowTypeVal: rowType
            property bool expandSubitem: true   // 是否展开子项
            property int itemShowHeight: columnDevice.height + 2 * columnDevice.spacing
            x: rowType==BluetoothDeviceModel.EnumRowType_Service ? 15 : 0
            width: listViewDevice.width - x
            height: {
                return itemShowHeight;//columnDevice.height + 2 * columnDevice.spacing;
                //return visible?columnDevice.height + 2 * columnDevice.spacing:0;
                //return textDeviceName.contentHeight + textDeviceAddr.contentHeight + textDeviceInfo1.contentHeight;//50//rowType==BluetoothDeviceModel.EnumRowType_Service ? 50 : 40//isVisible?40:0
            }
            state: "expand"
            opacity: 1
            smooth: true
            visible: true

            // 背景
            Rectangle {
                //id: background
                x: 2; y: 2;
                width: parent.width - x*2
                height: parent.height - y*2
                color: "ivory"
                border.color: "orange"
                radius: 5
            }
            // 鼠标响应
            MouseArea {
                anchors.fill: parent
                //propagateComposedEvents: true
                acceptedButtons: Qt.LeftButton | Qt.RightButton
                onClicked: {
                    //console.log("onClicked DeviceItem:" + index)
                    mouse.accepted = false;
                    listViewDevice.currentIndex = index
                    // 强制获取焦点，或者无法使用键盘上下键切换行
                    listViewDevice.forceActiveFocus();
                    // 单击折叠展开
                    if(rowType === BluetoothDeviceModel.EnumRowType_Device)
                    {
                        expandSubitem = !expandSubitem;
                        for(var i = index+1; i < listViewDevice.count; ++i)
                        {
                            //console.log(listViewDevice.itemAtIndex(i).rowTypeVal);
                            if(!listViewDevice.itemAtIndex(i))
                            {
                                break;
                            }
                            if(BluetoothDeviceModel.EnumRowType_Device === listViewDevice.itemAtIndex(i).rowTypeVal)
                            {
                                break;
                            }
                            if(listViewDevice.itemAtIndex(i).rowTypeVal > BluetoothDeviceModel.EnumRowType_Device)
                            {
                                //console.log(listViewDevice.itemAtIndex(i).state);
                                //listViewDevice.itemAtIndex(i).visible = expandSubitem;
                                listViewDevice.itemAtIndex(i).state = expandSubitem?"expand":"collapse";
                            }
                        }
                    }
                }
            }
            Item {
                //spacing: 10
                anchors.fill: parent
                Image {
                    id: imageListItem
                    width: 25
                    height: 25
                    anchors.verticalCenter: parent.verticalCenter
                    source: rowType == BluetoothDeviceModel.EnumRowType_Device?"/image/bluetooth.png":"/image/service.png"
                }
                Column{
                    id: columnDevice
                    spacing: 8
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.left: imageListItem.right
                    anchors.right: parent.right
                    //anchors.leftMargin: 2
                    //anchors.topMargin: 5
                    //anchors.bottomMargin: 5
                    Text {
                        //id: textDeviceName
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        //topPadding: 2
                        lineHeight: 0.7
                        text: {
                            if(rowType == BluetoothDeviceModel.EnumRowType_Device)
                            {
                                return deviceName.length > 0 ? deviceName : "未知"
                            }
                            else
                            {
                                return (serviceName.length > 0 ? serviceName : "未知");// + "  " + deviceAddr
                            }
                        }
                        font.family: customFont.name
                        font.bold: true
                        font.pixelSize: 15
                    }
                    Text {
                        id: textDeviceAddr
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        //topPadding: 2
                        lineHeight: 0.7
                        text: {
                            if(rowType == BluetoothDeviceModel.EnumRowType_Device)
                            {
                                return deviceAddr;
                            }
                            else
                            {
                                return serviceClassUuid;
                            }
                        }
                        anchors.topMargin: 2
                        font.family: customFont.name
                        //font.bold: true
                        font.pixelSize: 11
                        color: "gray"
                    }
                    Text {
                        id: textDeviceInfo1
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        //topPadding: 2
                        lineHeight: 0.7
                        text: {
                            if(rowType == BluetoothDeviceModel.EnumRowType_Device)
                            {
                                return (isLowEnergy?"<font color=\"blue\">低功耗</font>    ":"") + (isPaired?"<font color=\"green\">已配对</font>":"<font color=\"red\">未配对</font>") + "    " + "信号:" + rssi;
                            }
                            else
                            {
                                switch(socketProtocol)
                                {
                                case 0: return "Unknown Protocol";
                                case 1: return "L2cap Protocol";
                                case 2: return "Rfcomm Protocol";
                                default: return "Unknown Protocol";
                                }
                            }
                        }
                        visible: true
                        anchors.topMargin: 2
                        font.family: customFont.name
                        font.pixelSize: 11
                        color: "gray"
                    }
                    Row {
                        RoundButton {
                            id: btnDeviceOpenConnect
                            focus: true
                            //anchors.right: imageCollapseExpand.left
                            visible: rowType == BluetoothDeviceModel.EnumRowType_Device && !isLowEnergy ? false : true
                            text: {
                                if(rowType == BluetoothDeviceModel.EnumRowType_Device)
                                {
                                    return isLowEnergy?qsTr("打开"):qsTr("");
                                }
                                else
                                {
                                    return isSocketConnected?qsTr("断开"):qsTr("连接");
                                }
                            }
                            background: Rectangle {
                                //implicitWidth: delegateDeviceItem.height
                                //implicitHeight: delegateDeviceItem.height
                                radius: delegateDeviceItem.height / 2
                                opacity: enabled ? 1 : 0.3
                                color: btnDeviceOpenConnect.down ? "#d0d0d0" : "#e0e0e0"
                                border.color: "lightgreen"
                                scale: btnDeviceOpenConnect.down ? 1.1 : 1.0
                            }
                            onClicked: {
                                listViewDevice.currentIndex = index
                                console.log("click on btnDeviceOpenConnect:" + text + "  " + index + "  " + deviceAddr + "   " + serviceClassUuid);
                                if(rowType == BluetoothDeviceModel.EnumRowType_Device)
                                {
                                    BluetoothCtrlSingleton.connectLowEnergyDevice(deviceAddr);
                                    stackLayoutSearch.currentIndex = 1;

                                    textLowEnergyDeviceName.text = deviceName.length > 0 ? deviceName : "未知";
                                    textLowEnergyDeviceAddr.text = deviceAddr;
                                }
                                else if(rowType == BluetoothDeviceModel.EnumRowType_Service)
                                {
                                    if(text === qsTr("连接"))
                                    {
                                        BluetoothCtrlSingleton.connectSocket(deviceAddr, serviceClassUuid, socketProtocol);
                                    }
                                    else if(text === qsTr("断开"))
                                    {
                                        BluetoothCtrlSingleton.disconnectSocket();
                                    }
                                }
                            }
                        }
                    }
                }
                Image {
                    //id: imageCollapseExpand
                    anchors.right: parent.right
                    anchors.rightMargin: 10
                    width: 24
                    height: 12
                    anchors.verticalCenter: parent.verticalCenter
                    visible: (childItemCount>0?true:false)
                    source: expandSubitem?"/image/expand.png":"/image/collapse.png"
                }
            }
            // 状态值
            states: [
                // 折叠
                State {
                    name: "collapse"
                    PropertyChanges { target: delegateDeviceItem; height: 0; opacity: 0.0}
                }
                // 展开
                , State {
                    name: "expand"
                    PropertyChanges { target: delegateDeviceItem; height: itemShowHeight; opacity: 1.0 }
                }
                /*, State {// 当前选择行为当前
                    name: "Current"
                    when: delegateDeviceItem.ListView.isCurrentItem
                    PropertyChanges {
                        target: delegateDeviceItem;
                        x: 20
                    }
                }*/
            ]
            // 属性变化动画效果
            transitions: [
                Transition {
                    PropertyAnimation { property: "height"; duration: 250; }
                }
                /*, Transition {// 没效果，原因未知，使用Behavior有效果
                    //PropertyAnimation { property: "opacity"; duration: 300; }
                }*/
                /*
                , Transition {
                    NumberAnimation { properties: "x,y,contentY,height,width"; duration: 200 }
                }*/
            ]
            Behavior on opacity {
                PropertyAnimation { duration: 250 }
            }

            // 增删动画效果Animate adding and removing of items:
            ListView.onAdd: SequentialAnimation {
                PropertyAction { target: delegateDeviceItem; property: "height"; value: 0 }
                NumberAnimation { target: delegateDeviceItem; property: "height"; to: delegateDeviceItem.height; duration: 250; easing.type: Easing.InOutQuad }
            }
            ListView.onRemove: SequentialAnimation {
                PropertyAction { target: delegateDeviceItem; property: "ListView.delayRemove"; value: true }
                NumberAnimation { target: delegateDeviceItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad }

                // Make sure delayRemove is set back to false so that the item can be destroyed
                PropertyAction { target: delegateDeviceItem; property: "ListView.delayRemove"; value: false }
            }
        }
    }
    // 低功耗蓝牙信息列表delegate-------------------------------------------------------------------
    Component {
        id: delegateLowEnergyInfoList
        //
        Item {
            id: delegateLowEnergyInfoListItem
            property int rowTypeVal: rowType
            property bool expandSubitem: rowType === LowEnergyInfoModel.EnumRowType_Service?false:true   // 是否展开子项
            property int itemShowHeight: columnLowEnergyInfo.height + 2 * columnLowEnergyInfo.spacing
            x: {
                switch(rowType){
                case LowEnergyInfoModel.EnumRowType_Service: return 0;
                case LowEnergyInfoModel.EnumRowType_Characteristic: return 15;
                case LowEnergyInfoModel.EnumRowType_Descriptor: return 30;
                default: return 0;
                }
            }
            width: listViewLowEnergyInfo.width - x
            height: {
                return itemShowHeight;//columnLowEnergyInfo.height + 2 * columnLowEnergyInfo.spacing;
            }
            state: rowType === LowEnergyInfoModel.EnumRowType_Service?"expand":"collapse"//(expandSubitem?"expand":"collapse")//"expand"
            opacity: 1
            smooth: true
            visible: true
            // 背景
            Rectangle {
                //id: background
                x: 2; y: 2;
                width: parent.width - x*2
                height: parent.height - y*2
                color: "ivory"
                border.color: "orange"
                radius: 5
            }
            // 鼠标响应
            MouseArea {
                anchors.fill: parent
                //propagateComposedEvents: true
                acceptedButtons: Qt.LeftButton | Qt.RightButton
                onClicked: {
                    //console.log("onClicked LowEnergyInfoListItem:" + index)
                    mouse.accepted = false;
                    listViewLowEnergyInfo.currentIndex = index
                    // 强制获取焦点，或者无法使用键盘上下键切换行
                    listViewLowEnergyInfo.forceActiveFocus();
                    // 单击折叠展开
                    if(rowType === LowEnergyInfoModel.EnumRowType_Service || rowType === LowEnergyInfoModel.EnumRowType_Characteristic)
                    {
                        expandSubitem = !expandSubitem;
                        //console.log("expandSubitem:" + expandSubitem + ", rowType:" + rowType + ", clickon:" + (index) + ", count:" + listViewLowEnergyInfo.count);
                        let expandSubitemCharacteristic = expandSubitem;
                        for(var i = index+1; i < listViewLowEnergyInfo.count; ++i)
                        {
                            //console.log("i:" + i);
                            //console.log(listViewLowEnergyInfo.itemAtIndex(i).rowTypeVal);
                            if(!listViewLowEnergyInfo.itemAtIndex(i))
                            {
                                //console.log("itemAtIndex(" + i + ") is null:" + listViewLowEnergyInfo.itemAtIndex(i));
                                break;
                            }
                            if(listViewLowEnergyInfo.itemAtIndex(i).rowTypeVal <= rowType)
                            {
                                break;
                            }
                            if(!expandSubitem)
                            {
                                if(listViewLowEnergyInfo.itemAtIndex(i).rowTypeVal > rowType)
                                {
                                    //console.log(listViewLowEnergyInfo.itemAtIndex(i).state);
                                    //listViewLowEnergyInfo.itemAtIndex(i).visible = expandSubitem;
                                    listViewLowEnergyInfo.itemAtIndex(i).state = expandSubitem?"expand":"collapse";
                                }
                            }
                            else
                            {
                                if(listViewLowEnergyInfo.itemAtIndex(i).rowTypeVal === LowEnergyInfoModel.EnumRowType_Characteristic)
                                {
                                    expandSubitemCharacteristic = listViewLowEnergyInfo.itemAtIndex(i).expandSubitem;
                                    listViewLowEnergyInfo.itemAtIndex(i).state = expandSubitem?"expand":"collapse";
                                }
                                else if(listViewLowEnergyInfo.itemAtIndex(i).rowTypeVal === LowEnergyInfoModel.EnumRowType_Descriptor)
                                {
                                    listViewLowEnergyInfo.itemAtIndex(i).state = expandSubitemCharacteristic?"expand":"collapse";
                                }
                            }
                        }
                    }
                }
            }
            Item {
                anchors.fill: parent
                Image {
                    id: imageListItemLowEnergy
                    width: 25
                    height: 25
                    anchors.verticalCenter: parent.verticalCenter
                    source: {
                        switch(rowType){
                        case LowEnergyInfoModel.EnumRowType_Service: return "/image/service.png";
                        case LowEnergyInfoModel.EnumRowType_Characteristic: return "/image/Characteristic.png";
                        case LowEnergyInfoModel.EnumRowType_Descriptor: return "/image/Descriptor.png";
                        default: return "/image/service.png";
                        }
                    }
                }
                Column {
                    id: columnLowEnergyInfo
                    spacing: 8
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.left: imageListItemLowEnergy.right
                    anchors.right: parent.right
                    //anchors.leftMargin: 2
                    Text {
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        lineHeight: 0.7
                        text: {
                            switch(rowType){
                            case LowEnergyInfoModel.EnumRowType_Service: return (serviceName.length > 0 ? serviceName : "未知");
                            case LowEnergyInfoModel.EnumRowType_Characteristic: return (characteristicName.length > 0 ? characteristicName : "未知");
                            case LowEnergyInfoModel.EnumRowType_Descriptor: return (descriptorName.length > 0 ? descriptorName : "未知");
                            default: return "未知";
                            }
                        }
                        font.family: customFont.name
                        font.bold: true
                        font.pixelSize: 15
                    }
                    Text {
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        lineHeight: 0.7
                        text: {
                            switch(rowType){
                            case LowEnergyInfoModel.EnumRowType_Service: return serviceUuid;
                            case LowEnergyInfoModel.EnumRowType_Characteristic: return characteristicUuid;
                            case LowEnergyInfoModel.EnumRowType_Descriptor: return descriptorUuid;
                            default: return "未知";
                            }
                        }
                        //anchors.topMargin: 2
                        font.family: customFont.name
                        //font.bold: true
                        font.pixelSize: 11
                        color: "gray"
                    }
                    Text {
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        lineHeight: 0.7
                        text: {
                            if(rowType == LowEnergyInfoModel.EnumRowType_Characteristic)
                            {
                                let strProperty = "property:";
                                if(characteristicProperty & LowEnergyInfoModel.Broadcasting)
                                {
                                    strProperty += " Broadcasting"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.Read)
                                {
                                    strProperty += " Read"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.WriteNoResponse)
                                {
                                    strProperty += " WriteNoResponse"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.Write)
                                {
                                    strProperty += " Write"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.Notify)
                                {
                                    strProperty += " Notify"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.Indicate)
                                {
                                    strProperty += " Indicate"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.WriteSigned)
                                {
                                    strProperty += " WriteSigned"
                                }
                                if(characteristicProperty & LowEnergyInfoModel.ExtendedProperty)
                                {
                                    strProperty += " ExtendedProperty"
                                }
                                return strProperty;
                            }
                            else
                            {
                                height = 0;
                                return "";
                            }
                        }
                        //anchors.topMargin: 2
                        font.family: customFont.name
                        //font.bold: true
                        font.pixelSize: 11
                        color: "gray"
                    }
                    Text {
                        width: parent.width
                        wrapMode: TextArea.WrapAnywhere
                        lineHeight: 0.7
                        text: {
                            if(rowType == LowEnergyInfoModel.EnumRowType_Characteristic || rowType == LowEnergyInfoModel.EnumRowType_Descriptor)
                            {
                                return "value:" + chDescValue;
                            }
                            else
                            {
                                height = 0;
                                return "";
                            }
                        }
                        //anchors.topMargin: 2
                        font.family: customFont.name
                        //font.bold: true
                        font.pixelSize: 11
                        color: "gray"
                    }
                    Row {
                        spacing: 10
                        RoundButton {
                            //id: btnLowEnergyRead
                            focus: true
                            //anchors.right: parent.right
                            visible: rowType == LowEnergyInfoModel.EnumRowType_Service ? false : true
                            enabled: rowType == LowEnergyInfoModel.EnumRowType_Service ? false : true
                            text: {
                                switch(rowType)
                                {
                                case LowEnergyInfoModel.EnumRowType_Service:
                                    return qsTr("");
                                case LowEnergyInfoModel.EnumRowType_Characteristic:
                                    return qsTr("读");
                                case LowEnergyInfoModel.EnumRowType_Descriptor:
                                    return qsTr("读");
                                default:
                                }
                                return qsTr("");
                            }
                            background: Rectangle {
                                //implicitWidth: delegateLowEnergyInfoListItem.height
                                //implicitHeight: delegateLowEnergyInfoListItem.height
                                radius: delegateLowEnergyInfoListItem.height / 2
                                opacity: enabled ? 1 : 0.3
                                color: parent.down ? "#d0d0d0" : "#e0e0e0"
                                border.color: "lightgreen"
                                scale: parent.down ? 1.1 : 1.0
                            }
                            onClicked: {
                                listViewLowEnergyInfo.currentIndex = index
                                console.log("click on low energy item:" + text + "  " + index + ", rowType:" + rowType);
                                if(rowType == LowEnergyInfoModel.EnumRowType_Characteristic)
                                {
                                    BluetoothCtrlSingleton.readLowEnergyCharacteristic(characteristicName, characteristicUuid, serviceName, serviceUuid);
                                }
                                else if(rowType == LowEnergyInfoModel.EnumRowType_Descriptor)
                                {
                                    BluetoothCtrlSingleton.readLowEnergyDescriptor(descriptorName, descriptorUuid
                                                                                   , characteristicUuid
                                                                                   , serviceUuid
                                                                                   );
                                }
                            }
                        }
                        RoundButton {
                            //id: btnLowEnergyWrite
                            focus: true
                            //anchors.right: parent.right
                            visible: rowType == LowEnergyInfoModel.EnumRowType_Service ? false : true
                            enabled: rowType == LowEnergyInfoModel.EnumRowType_Service ? false : true
                            text: {
                                switch(rowType)
                                {
                                case LowEnergyInfoModel.EnumRowType_Service:
                                    return qsTr("");
                                case LowEnergyInfoModel.EnumRowType_Characteristic:
                                    return qsTr("发送");
                                case LowEnergyInfoModel.EnumRowType_Descriptor:
                                    return qsTr("写");
                                default:
                                }
                                return qsTr("");
                            }
                            background: Rectangle {
                                //implicitWidth: delegateLowEnergyInfoListItem.height
                                //implicitHeight: delegateLowEnergyInfoListItem.height
                                radius: delegateLowEnergyInfoListItem.height / 2
                                opacity: enabled ? 1 : 0.3
                                color: parent.down ? "#d0d0d0" : "#e0e0e0"
                                border.color: "lightgreen"
                                scale: parent.down ? 1.1 : 1.0
                            }
                            onClicked: {
                                listViewLowEnergyInfo.currentIndex = index
                                console.log("click on low energy item:" + text + "  " + index + ", rowType:" + rowType);
                                if(rowType == LowEnergyInfoModel.EnumRowType_Characteristic)
                                {
                                    if(BluetoothCtrlSingleton.selectLowEnergyCharacteristic(characteristicName, characteristicUuid, serviceName, serviceUuid))
                                    {
                                        swipeView.setCurrentIndex(1);
                                    }
                                }
                                else if(rowType == LowEnergyInfoModel.EnumRowType_Descriptor)
                                {
                                    dialogSetDescriptor.setDescriptorValue(descriptorName, descriptorUuid
                                                                           , characteristicUuid
                                                                           , serviceUuid, chDescValue);
                                    dialogSetDescriptor.open();
                                }
                            }
                        }
                        RoundButton {
                            // Client Characteristic Configuration
                            // Enable notifications
                            // 开启接收数据
                            //id: btnLowEnergyEnableReceiveNotify
                            focus: true
                            //anchors.right: parent.right
                            visible: descriptorUuid === qsTr("{00002902-0000-1000-8000-00805f9b34fb}") ? true : false
                            enabled: descriptorUuid === qsTr("{00002902-0000-1000-8000-00805f9b34fb}") ? true : false
                            text: qsTr("使能接收通知")
                            background: Rectangle {
                                //implicitWidth: delegateLowEnergyInfoListItem.height
                                //implicitHeight: delegateLowEnergyInfoListItem.height
                                radius: delegateLowEnergyInfoListItem.height / 2
                                opacity: enabled ? 1 : 0.3
                                color: parent.down ? "#d0d0d0" : "#e0e0e0"
                                border.color: "lightgreen"
                                scale: parent.down ? 1.1 : 1.0
                            }
                            onClicked: {
                                listViewLowEnergyInfo.currentIndex = index
                                console.log("click on low energy item:" + text + "  " + index + ", rowType:" + rowType);
                                if(rowType == LowEnergyInfoModel.EnumRowType_Descriptor)
                                {
                                    if(1) {// 使能notification
                                        BluetoothCtrlSingleton.writeLowEnergyDescriptor(descriptorName, descriptorUuid
                                                                                        , characteristicUuid
                                                                                        , serviceUuid
                                                                                        , "0100"
                                                                                        , BluetoothCtrlSingleton.EnumCharset_HEX
                                                                                        );
                                    } else {// 使能indicate
                                        BluetoothCtrlSingleton.writeLowEnergyDescriptor(descriptorName, descriptorUuid
                                                                                        , characteristicUuid
                                                                                        , serviceUuid
                                                                                        , "0200"
                                                                                        , BluetoothCtrlSingleton.EnumCharset_HEX
                                                                                        );
                                    }
                                }
                            }
                        }
                    }
                }
                Image {
                    //id: imageCollapseExpand
                    anchors.right: parent.right
                    anchors.rightMargin: 10
                    width: 24
                    height: 12
                    visible: (childItemCount>0?true:false)
                    anchors.verticalCenter: parent.verticalCenter
                    source: expandSubitem?"/image/expand.png":"/image/collapse.png"
                }
            }
            // 状态值
            states: [
                // 折叠
                State {
                    name: "collapse"
                    PropertyChanges { target: delegateLowEnergyInfoListItem; height: 0; opacity: 0.0}
                }
                // 展开
                , State {
                    name: "expand"
                    PropertyChanges { target: delegateLowEnergyInfoListItem; height: itemShowHeight; opacity: 1.0 }
                }
                /*, State {// 当前选择行为当前
                    name: "Current"
                    when: delegateLowEnergyInfoListItem.ListView.isCurrentItem
                    PropertyChanges {
                        target: delegateLowEnergyInfoListItem;
                        x: 20
                    }
                }*/
            ]
            // 属性变化动画效果
            transitions: [
                Transition {
                    PropertyAnimation { property: "height"; duration: 250; }
                }
                /*, Transition {// 没效果，原因未知，使用Behavior有效果
                    //PropertyAnimation { property: "opacity"; duration: 300; }
                }*/
                /*
                , Transition {
                    NumberAnimation { properties: "x,y,contentY,height,width"; duration: 200 }
                }*/
            ]
            Behavior on opacity {
                PropertyAnimation { duration: 250 }
            }

            // 增删动画效果Animate adding and removing of items:
            ListView.onAdd: SequentialAnimation {
                PropertyAction { target: delegateLowEnergyInfoListItem; property: "height"; value: 0 }
                NumberAnimation { target: delegateLowEnergyInfoListItem; property: "height"; to: delegateLowEnergyInfoListItem.height; duration: 250; easing.type: Easing.InOutQuad }
            }
            ListView.onRemove: SequentialAnimation {
                PropertyAction { target: delegateLowEnergyInfoListItem; property: "ListView.delayRemove"; value: true }
                NumberAnimation { target: delegateLowEnergyInfoListItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad }

                // Make sure delayRemove is set back to false so that the item can be destroyed
                PropertyAction { target: delegateLowEnergyInfoListItem; property: "ListView.delayRemove"; value: false }
            }
        }
    }

    // 项高亮组件
    Component {
        id: highlightDevice
        Rectangle {
            // parent在列表不显示时会变为null
            // parent.parent是ListView
            x: parent&&parent.parent.currentItem ? parent.parent.currentItem.x : 0
            y: parent&&parent.parent.currentItem ? parent.parent.currentItem.y : 0
            width: parent&&parent.parent.currentItem ? parent.parent.currentItem.width : 0
            height: parent&&parent.parent.currentItem ? parent.parent.currentItem.height : 0
            color: "lightsteelblue"
            border.color: "lightgreen"
            border.width: 4
            radius: 5
            Behavior on y {
                SpringAnimation { spring: 3; damping: 0.3 }
            }
        }
    }
    /////////////////////////////////////////
    listViewDevice{
        onFocusChanged: {

        }
        // 分组分块
        /*section.property: "sectionInfo"
        section.criteria: ViewSection.FullString
        section.labelPositioning: ViewSection.InlineLabels//|ViewSection.CurrentLabelAtStart
        section.delegate: ToolBar {
            width: listViewDevice.width
            Label {
                text: section.toString()
                anchors.fill: parent
                horizontalAlignment: Qt.AlignHCenter
                verticalAlignment: Qt.AlignVCenter
                Component.onCompleted: {
                    //console.log(bluetoothDeviceModel);
                }
            }
        }*/
    }
    listViewLowEnergyInfo{

    }

    //Connections{
    //    target: mouseAreaList
    //onClicked: {
    //    mouse.accepted = false;
    // 强制获取焦点，或者无法使用键盘上下键切换行
    //listViewDevice.forceActiveFocus();
    //}
    //}

    editDeviceFilter {
        onTextEdited: {
            //console.log("onTextEdited:" + editDeviceFilter.text);
            BluetoothCtrlSingleton.setDeviceFilter(editDeviceFilter.text);
        }
    }

    searchBtn{
        onClicked: {
            if(searchBtn.text == qsTr("搜索"))
            {
                BluetoothCtrlSingleton.startScan();
            }
            else if(searchBtn.text == qsTr("停止设备搜索"))
            {
                BluetoothCtrlSingleton.stopDeviceScan();
            }
            else if(searchBtn.text == qsTr("停止服务搜索"))
            {
                BluetoothCtrlSingleton.stopServiceScan();
            }
            else
            {
                console.log("searchBtn text unkown");
            }

            //bluetoothDeviceModel.add("未知", 2, "{00001101-0000-1000-8000-234235325}", "HC-05" , "20:00:15:25::65:87");
            //listViewDevice.model.add("未知", 2, "{00001101-0000-1000-8000-234235325}", "HC-05" , "20:00:15:25::65:87");
            //return;

            //bluetoothDeviceModel.clear();
            //BluetoothCtrlSingleton.startDeviceScan();
            //BluetoothCtrlSingleton.startServiceScan();
            //BluetoothCtrlSingleton.startScan();

            /*
            listViewDevice.currentIndex = 1
            bluetoothDeviceModel.append({
                                       name: new Date().toTimeString(),
                                       addr: new Date().toDateString(),
                                       colorCode: "green"
                                   });
            */
        }
    }
    btnReturnSearch{
        onClicked: {
            stackLayoutSearch.currentIndex = 0;
            BluetoothCtrlSingleton.disconnectLowEnergyDevice();
        }
    }

}

